/*
此处是终端节点，在原本基础上将传感和控制结合在一起。传感部分无需做变化，而控制部分需要把原本的直接控制开/关/占空比
改为接收参数的合理范围，并通过与范围的比对自动决定应该如何处理。请最好不要一次开启过多电机。
*/
#include "pinctrl.h"
#include "soc_osal.h"
#include "uart.h"
#include "watchdog.h"
#include "adc.h"
#include "adc_porting.h"
#include "osal_debug.h"
#include "cmsis_os2.h"
#include "app_init.h"
#include "gpio.h"
#include "i2c.h"

#include "securec.h"
#include "errcode.h"
#include "osal_addr.h"
#include "sle_common.h"
#include "sle_errcode.h"
#include "sle_ssap_server.h"
#include "sle_connection_manager.h"
#include "sle_device_discovery.h"

#include "CO2.h"
#include "temp_mois.h"
#include "pH_TDS_DO_LIGHT.h"
#include "water.h"
#include "sle_server.h"
#include "sle_server_adv.h"
#include "ws2812.h"
#include "main.h"

#include "pwm.h"
#include "tcxo.h"

#include "my_pwm.h"
#include "my_gpio.h"

uint32_t CO2_low = 0;
uint32_t CO2_high = 0;

float pH_low = 0;
float pH_high = 0;

float TDS_low = 0;
float TDS_high = 0;

float DO_low = 0;
float DO_high = 0;

uint32_t temp_low = 0;
uint32_t temp_high = 0;

uint32_t humi_low = 0;
uint32_t humi_high = 0;

float light_low = 0;
float light_high = 0;

uint8_t sle_tx_buff[SLE_TX_LENGTH] = { 0 };//将所有数据汇总，通过星闪发送出去

/*
接收数据帧格式1：0xFF 二氧化碳 pH值 TDS值 溶解氧 温度 湿度 光照 0xFF（此时认为传来的是阈值下限）
接收数据帧格式2：0xFF 二氧化碳 pH值 TDS值 溶解氧 温度 湿度 光照 0xFE（此时认为传来的是阈值上限）
接收数据帧格式3：0xFF 灯条 碱性水泵 营养液泵 风扇 加热器 酸性水泵 加湿器 0xFE（此时认为传来的是手动调节命令，0表
示关1表示开）
汇总通过星闪接收到的、所有参数（除水位）的最佳范围。
*/
uint8_t sle_rx_buff[SLE_RX_LENGTH] = { 0 };

uint8_t manual = 1; //该值为1时代表人工操作，此时不再自行判断应该如何控制电机

char* uart_rx_message[] = {
    "\nLIGHT:",
    "BUMP_ALKALI:",
    "BUMP_NUTRITION:",
    "FAN:",
    "HEATER:",
    "BUMP_ACID:",
    "HUMIDIFIER:"
};

uint8_t regulation_table[regulation_num] = {0};

/*
发送数据帧格式设置：0xFF 二氧化碳 pH值 TDS值 溶解氧 温度 湿度 光照 0xFE
*/
static void *sensor_task(const char *arg)
{
    unused(arg);
    CO2_init();
    SHT30_init();
    
    pH_TDS_DO_LIGHT_init();
    water_init();

    sle_tx_buff[0] = 0xFF;//设置数据帧格式
    sle_tx_buff[SLE_TX_LENGTH - 1] = 0xFE;

    enable_sle();
    sle_conn_register_cbks();
    sle_ssaps_register_cbks();
    sle_uuid_server_add();
    sle_uuid_server_adv_init();
    osal_printk("[uuid server] init ok\r\n");
    while (1)
    {
        osal_printk("\r\nsensor project running...\r\n");
        SHT30_Read_Humiture();
        pH_TDS_DO_LIGHT_read();

        for (uint8_t i = 0; i < SLE_TX_LENGTH; i++)
        {
            osal_printk("%X ", sle_tx_buff[i]);
        }
        osal_printk("\r\n");
        sle_uuid_server_send_report_by_handle(sle_tx_buff, SLE_TX_LENGTH);
        osal_msleep(1000);
    }
    return NULL;
}

// 由最佳阈值和当前数据推算应当怎样驱动调节器
void get_regulation_table(void)
{
    for (uint8_t i = 0; i < len; i++)
    {
        osal_printk("%x ", sle_rx_buff[i]);
    }
    osal_printk("len = %d\r\n", len);
    if (len == regulation_num + 2)
    {
        manual = 1;
        for (uint8_t i = 0; i < regulation_num; i++)
        {
            regulation_table[i] = sle_rx_buff[i + 1];
        }
        return;
    }
    else if (len == SLE_RX_LENGTH)
    {
        manual = 0;
    }
    else
    {
        osal_printk("len = %d\r\n", len);
    }
    memcpy(&CO2_low, &(sle_rx_buff[CO2]), 4);
    memcpy(&CO2_high, &(sle_rx_buff[CO2 + SPAN]), 4);
    osal_printk("CO2 low is :%d, CO2 high is :%d\r\n", CO2_low, CO2_high);
    if (co2 < CO2_low)
    {
        regulation_table[FAN] = 0;
        osal_printk("fan off\r\n");
    }
    if (co2 > CO2_high)
    {
        regulation_table[FAN] = 80;
        osal_printk("fan on\r\n");
    }
    
    memcpy(&pH_low, &sle_rx_buff[PH], 4);
    memcpy(&pH_high, &sle_rx_buff[PH + SPAN], 4);
    osal_printk("pH low is :%d.%d, pH high is :%d.%d\r\n",
        (int)pH_low,
        (int)(pH_low * 100.f) - (int)pH_low * 100,
        (int)pH_high,
        (int)(pH_high * 100.f) - (int)pH_high * 100);
    if (pH < pH_low)
    {
        regulation_table[BUMP_ACID] = 0;
        regulation_table[BUMP_ALKALI] = 1;
        osal_printk("bump alkali on\r\n");
    }
    if (pH > pH_high)
    {
        regulation_table[BUMP_ACID] = 1;
        regulation_table[BUMP_ALKALI] = 0;
        osal_printk("bump acid on\r\n");
    }

    memcpy(&TDS_low, &sle_rx_buff[TDS], 4);
    memcpy(&TDS_high, &sle_rx_buff[TDS + SPAN], 4);
    osal_printk("TDS low is :%d.%d, TDS high is :%d.%d\r\n",
        (int)TDS_low,
        (int)(TDS_low * 100.f) - (int)TDS_low * 100,
        (int)TDS_high,
        (int)(TDS_high * 100.f) - (int)TDS_high * 100);
    if (tds > TDS_high)
    {
        regulation_table[BUMP_NUTRITION] = 0;
        osal_printk("bump butrition off\r\n");
    }
    if (tds < TDS_low)
    {
        regulation_table[BUMP_NUTRITION] = 1;
        osal_printk("bump butrition on\r\n");
    }

    memcpy(&DO_low, &sle_rx_buff[DO], 4);
    memcpy(&DO_high, &sle_rx_buff[DO + SPAN], 4);
    osal_printk("DO low is :%d.%d, DO high is :%d.%d\r\n",
        (int)DO_low,
        (int)(DO_low * 100.f) - (int)DO_low * 100,
        (int)DO_high,
        (int)(DO_high * 100.f) - (int)DO_high * 100);
    if (do_value > DO_high)
    {
        regulation_table[FAN] = 0;
        osal_printk("fan off\r\n");
    }
    if (do_value < DO_low)
    {
        regulation_table[FAN] = 1;
        osal_printk("fan on\r\n");
    }

    memcpy(&light_low, &sle_rx_buff[LIGHT], 4);
    memcpy(&light_high, &sle_rx_buff[LIGHT + SPAN], 4);
    osal_printk("light low is :%d.%d, light high is :%d.%d\r\n",
        (int)light_low,
        (int)(light_low * 100.f) - (int)light_low * 100,
        (int)light_high,
        (int)(light_high * 100.f) - (int)light_high * 100);
    if (light < light_low)
    {
        ws2812_on();
        osal_printk("light on\r\n");
    }
    if (light > light_high)
    {
        ws2812_off();
        osal_printk("light off\r\n");
    }

    memcpy(&temp_low, &sle_rx_buff[TEMP], 4);
    memcpy(&temp_high, &sle_rx_buff[TEMP + SPAN], 4);
    osal_printk("temp low is :%d, temp high is :%d\r\n", temp_low, temp_high);
    if (temp > (int)temp_high)
    {
        regulation_table[HEATER] = 0;
        osal_printk("heater off\r\n");
    }
    if (temp < (int)temp_low)
    {
        regulation_table[HEATER] = 1;
        osal_printk("heater on\r\n");
    }

    memcpy(&humi_low, &sle_rx_buff[MOIS], 4);
    memcpy(&humi_high, &sle_rx_buff[MOIS + SPAN], 4);
    osal_printk("humi low is :%d, humi high is :%d\r\n", humi_low, humi_high);
    if (humi > humi_high)
    {
        regulation_table[HUMIDIFIER] = 0;
        osal_printk("humidifier off\r\n");
    }
    if (humi < humi_low)
    {
        regulation_table[HUMIDIFIER] = 1;
        osal_printk("humidifier on\r\n");
    }
}

static void *regulation_task(const char *arg)
{
    UNUSED(arg);
    sle_rx_buff[0] = 0xff;
    sle_rx_buff[SLE_RX_LENGTH - 1] = 0xfd;
    enable_sle();
    sle_conn_register_cbks();
    sle_ssaps_register_cbks();
    sle_uuid_server_add();
    sle_uuid_server_adv_init();
    osal_printk("[uuid server] init ok\r\n");

    init_all_pwm();
    init_all_gpio();
    uapi_pwm_start_group(FAN);

    ws2812_init();

    uint8_t i = 1;
    uint8_t j;
    while(1)
    {
        get_regulation_table();
        osal_printk("\r\nregulation project running...\r\n");
        for (uint8_t i = 0; i < regulation_num; i++)
        {
            osal_printk("%s%d\r\n", uart_rx_message[i], ((uint8_t* )regulation_table)[i]);
            if(i == FAN)
            {
                pwm_update_duty_ratio(i, i, (1 - regulation_table[i]) * 80);
            }
            else if(i == LAMP)
            {
                if (regulation_table[i])
                    ws2812_on();
                else
                    ws2812_off();
            }
            else
            {
                uapi_gpio_set_val(i, regulation_table[i]);
            }
        }
        
        // for (j = 1; j < 7; j++)
        // {
        //     // osal_printk("%s%d\r\n", uart_rx_message[i], ((uint8_t* )regulation_table)[i + 1]);
        //     if(j == FAN)
        //     {
        //         pwm_update_duty_ratio(j, FAN, (i == j) * 80);
        //     }
        //     else
        //     {
        //         uapi_gpio_set_val(i, (i == j));
        //     }
        // }
        // osal_printk("\r\n");
        // if (i != 6)
        // {
        //     i++;
        // }
        // else
        // {
        //     i = 1;
        // }
        osal_msleep(1000);
    }
    return NULL;
}

static void farm_project_entry(void)
{
    osal_task *task_handle = NULL;
    osal_kthread_lock();
    task_handle = osal_kthread_create((osal_kthread_handler)sensor_task, 0, "SensorTask", SENSOR_TASK_STACK_SIZE);
    if (task_handle != NULL)
    {
        osal_kthread_set_priority(task_handle, SENSOR_TASK_PRIO);
    }

    task_handle = osal_kthread_create((osal_kthread_handler)regulation_task, 0, "RegulationTask", REGULATION_TASK_STACK_SIZE);
    if (task_handle != NULL)
    {
        osal_kthread_set_priority(task_handle, REGULATION_TASK_PRIO);
    }
    osal_kthread_unlock();
}

app_run(farm_project_entry);

